#include "admediacontext.h"
#include <QRegExp>
#include <QDebug>

AdMediaContext::AdMediaContext()
{
}

AdMediaContext::~AdMediaContext(){
    ClearAllMedias();
}

QSharedPointer<AdMediaContext> AdMediaContext::_instance = QSharedPointer<AdMediaContext>(new AdMediaContext());

QSharedPointer<AdMediaContext> AdMediaContext::GetInstance(){
    return _instance;
}

void AdMediaContext::MediaRegistry(int media_id, int proj_id, const QString &media_cn, const QString &media_name, const QString &attr, int floor_, const QString &area_)
{
    SimpleInfo *simple = new SimpleInfo(media_id, proj_id, media_cn, media_name, attr, floor_, area_);
    if(IsRegistied(simple)) return;

    if(_name_map.contains(media_name)){
        if(!_name_map[media_name].contains(media_cn)) _name_map[media_name].push_back(media_cn);
    }else{
        QList<QString> media_cn_lst;
        media_cn_lst <<media_cn;
        _name_map[media_name] = media_cn_lst;
    }

    QString floor, area, floorarea, blank, key;
    blank = "";
    floor = floor_ == 10000 ? "" : QString::number(floor_);
    area = area_;
    floorarea = QString("%1%2").arg(floor, area);
    key = simple->media_cn + simple->media_name + simple->attr;

    QList<SimpleInfo *> ls;
    ls << simple;

    _contains << simple;

    if(_hash_map.contains(key)){
        int index = _hash_map[key];

        if(_medias[index].contains(floor)) _medias[index][floor].append(ls);
        else _medias[index][floor] = ls;

        if(_medias[index].contains(area)) _medias[index][area].append(ls);
        else _medias[index][area] = ls;

        if(_medias[index].contains(floorarea))_medias[index][floorarea].append(ls);
        else _medias[index][floorarea] = ls;

        if(_medias[index].contains(blank))_medias[index][blank].append(ls);
        else _medias[index][blank] = ls;
    }else{
        QHash<QString, QList<SimpleInfo* > > tmp;
        tmp[floor] = ls;
        tmp[area] = ls;
        tmp[floorarea] = ls;
        tmp[blank] = ls;
        _hash_map[key] = _medias.size();
        _medias.push_back(tmp);
    }

}

void AdMediaContext::MediasRegistry(int media_id, int proj_id, const QString &media_cn, const QString &media_name, const QString &attrs, int floor, const QString &area){
    QStringList attr_list = attrs.split(";");
    for(int i=0; i<attr_list.size(); i++) MediaRegistry(media_id, proj_id, media_cn, media_name, attr_list[i], floor, area);
}

void AdMediaContext::ScenesRegistry(const QString &scenes, int media_id, int proj_id, int floor, const QString &area){

    MediaRegistry(media_id, proj_id, "场景", "scene", "scene", floor, area);
    MediaRegistry(media_id, proj_id, "模式", "scene", "scene", floor, area);
    QStringList scene_values = scenes.split(";");
    QString key;
    for(int i=0; i<scene_values.size(); i++){
        QString scene_name = scene_values[i];
        if(scene_name.trimmed().length()==0) continue;
        key = QString::number(media_id) + "," + QString::number(proj_id) + "," + scene_name.trimmed();
        _scene_keys.insert(key);
    }
}

void AdMediaContext::ClearAllMedias(){
    _hash_map.clear();
    _name_map.clear();
    _medias.clear();
    for(int i=0;i< _contains.size(); i++){
         delete _contains[i];
         _contains[i] = NULL;
     }
    _contains.clear();
}

void AdMediaContext::ClearMedia(int media_id, int proj_id, const QString &media_cn, const QString &media_name, const QString &attr, int floor, const QString &area){
    SimpleInfo *simple = new SimpleInfo(media_id, proj_id, media_cn, media_name, attr, floor,area);
    if(!IsRegistied(simple)) return;

    int c = 0;
    SimpleInfo *ptr=NULL;

    for(int i=0; i<_contains.size(); ++i){
        if(*simple == *_contains[i]){
            ptr = _contains[i];
            c = i;
            break;
        }
    }

    if(ptr == NULL) return;

    QString _key = simple->media_cn + simple->media_name + simple->attr;

    int ind = _hash_map[_key];

    for(int kk=0; kk< _medias[ind].keys().size(); kk++){
            QString key = _medias[ind].keys()[kk];
            for(int i=_medias[ind][key].size()-1; i>=0 ; i--){ //必须从后往前
               if(ptr == _medias[ind][key][i]) _medias[ind][key].removeAt(i);
            }
    }
    _contains.removeAt(c);
    delete ptr;
    ptr = NULL;
}

void AdMediaContext::drop_duplicates(QList<SimpleInfo> &datas){
    for(int i=0; i<datas.size(); i++){
        for(int j=datas.size()-1; j>i; --j){
            if(datas[i]==datas[j]) datas.removeAt(j);
        }
    }
}

QList<SimpleInfo> AdMediaContext::GetAllRegistriedMedias(const QString &media_cn, const QString &media_name, const QString &attr, int floor, const QString &area){
    QList<SimpleInfo> result;
    QString key = media_cn + media_name + attr;
    if(!_hash_map.contains(key)) return result;
    SimpleInfo *simple = new SimpleInfo(-1, -1, media_cn, media_name, attr, floor, area);
    QHash<QString,QList<SimpleInfo*> > hash = _medias[_hash_map[key]];
    QString floor_area;
    if(simple->floor != -10000) floor_area = QString("%1%2").arg(QString::number(simple->floor), simple->area);
    else floor_area = simple->area;
    if(hash.contains(floor_area)){
        QList<SimpleInfo*> tmp = hash[floor_area];
        for(int i=0; i< tmp.size(); ++i) result.push_back(SimpleInfo(*(tmp[i])));
    }
    drop_duplicates(result);
    return result;
}

//单个筛选, status :1.解析失败, 3.确定名称+只匹配到大类  4未定名称匹配 + 非场景匹配结果, 5.未定名称匹配 + 场景匹配结果, 6.名称确定匹配结果, 数字高则优先级高
QList<ADDataType> AdMediaContext::FilterCommandS(const ADDataType &data, int &status){
    QList<ADDataType> result;
    if(!data.Success) {
        status = 1;
        return result;
    }


    QString str_floor = data.floor;
    int floor = str_floor.length() == 0 ? -10000 : str_floor.replace(QRegExp("[^\\d]"), "").toInt();

    if(!data.name_is_sure){
        status = data.is_scene ? 5:4;
        QList<QString> media_cns = _name_map.value(data.media_name);
        for(int ij=0; ij<media_cns.size(); ij++){
            QString media_cn = media_cns[ij];
            QList<SimpleInfo> simples = GetAllRegistriedMedias(media_cn, data.media_name, data.attri, floor, data.area);
            for(int i=0; i<simples.size(); i++){
                ADDataType tmp(data);
                tmp.floor = simples[i].floor==-10000? "":QString::number(simples[i].floor);
                tmp.media_cn = media_cn;
                tmp.area = simples[i].area;
                tmp.media_id =simples[i].media_id;
                tmp.proj_id = simples[i].proj_id;
                result.push_back(tmp);
            }
        }
    }else{
        status = 6;
        QList<SimpleInfo> simples = GetAllRegistriedMedias(data.media_cn, data.media_name, data.attri, floor, data.area);

        for(int i=0; i<simples.size(); i++){
            ADDataType tmp(data);
            tmp.floor = simples[i].floor==-10000? "":QString::number(simples[i].floor);
            tmp.area = simples[i].area;
            tmp.media_id =simples[i].media_id;
            tmp.proj_id = simples[i].proj_id;

            result.push_back(tmp);
        }

        if(result.empty()){
            status = 3;
            QList<QString> media_cns = _name_map.value(data.media_name);
            for(int jk=0; jk < media_cns.size(); jk++){
                QString media_cn = media_cns[jk];
                QList<SimpleInfo> simples = GetAllRegistriedMedias(media_cn, data.media_name, data.attri, floor, data.area);
                for(int i=0; i<simples.size(); i++){
                    ADDataType tmp(data);
                    tmp.floor = QString::number(simples[i].floor);
                    tmp.media_cn = media_cn;
                    tmp.area = simples[i].area;
                    tmp.media_id =simples[i].media_id;
                    tmp.proj_id = simples[i].proj_id;
                    result.push_back(tmp);
                }
            }
        }
    }
    return result;
}

QList<ADDataType> AdMediaContext::FilterCommandS(QList<ADDataType> &datas, int &prior, int floor, QString area){
    QList<ADDataType> result;
    prior = 1;
    if(datas.empty()) return result;
    for(int i=0; i<datas.size(); i++){
        int _status = 0;
        QList<ADDataType> tmp = FilterCommandS(datas[i], _status);
        if(_status > prior){
            result = tmp;
            prior = _status;
        }else if(_status == prior){ //针对不确定的解析结果，比如 音量调大 (电视/背景音乐)
            result.append(tmp);
        }
    }

    if(floor != -10000){
        for(int i=result.size()-1; i>=0; --i){
            if(result[i].floor != QString::number(floor)) result.removeAt(i);
        }
    }

    if(area.length() > 0){
        for(int i=result.size()-1; i>=0; --i){
            if(result[i].area != area) result.removeAt(i);
        }
    }

    scene_filter(result);
    return result;
}

bool AdMediaContext::IsRegistied(SimpleInfo * const &data){
    bool res = false;
    for(int i=0; i<_contains.size(); i++){
        if(*_contains[i] == *data){res = true; break;}
    }
    return res;
}

void AdMediaContext::scene_filter(QList<ADDataType> &datas){
    for(int i=datas.size()-1; i>=0; --i){
        if(datas[i].media_name == "scene"){
             QString cn_name = datas[i].value_cn;
             QString key = QString::number(datas[i].media_id) + "," + QString::number(datas[i].proj_id) + "," + cn_name;
             if(!_scene_keys.contains(key)) datas.removeAt(i);
            }
    }
}
